package DRC.DRModbus;

import DRC.DRCDB;
import DRC.channel;
import DRC.channel4collect;
import DRC.dataItem4collect;
import DRCOMM.DRHTTP_API;
import DRCOMM.DR_SESSION;
import DRCOMM.FJW_URI;
import DRCOMM.dr_ajax_answer;
import DRCOMM.dr_util;
import DRCOMM.record_data_set;
import com.fazecast.jSerialComm.SerialPort;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class DRModbus_RTU_Master extends Thread{

    // 定义常量
    final public static int REGISTER_TYPE_COILS = 1;
    final public static int REGISTER_TYPE_DISCRETE_INPUTS = 2;
    final public static int REGISTER_TYPE_HOLDING_REGISTERS = 3;
    final public static int REGISTER_TYPE_INPUT_REGISTERS = 4;
    
    final public static int DATA_SINGED = 1;
    final public static int DATA_LONG = 2;
    final public static int DATA_FLOAT = 3;
    final public static int DATA_DOUBLE = 4;
    
    DRCDB drcdb;
    public String com;
    public int band_rate;
    public int parity;
    public int stop;
    public int channel_id;
    public byte[] recive_buff=new byte[2048];
    public boolean runMark=true;   //运行标志
    public int run_cycle=60;        //采集周期变量
    public int IntervalTime;
    public String name="";
    public int function_code=3;
    public int slave_id=1;
    public int address=0;
    public int count=0;
    public int dataitem_type=1;
    private static int max_group_size=100;

    private static String logPrefix = "./log/Modbus/ModbusRTUMaster_";

    public static ArrayList<channel> channels=null;
    public static ArrayList<channel4collect> channels4collect=null;

    public DRModbus_RTU_Master(DRCDB drcdb,
                               String com, int band_rate, int parity, int stop,
                               int channel_id, String name,
                               int function_code, int slave_id, int address, int count,
                               int dataitem_type, int run_cycle, int IntervalTime){
        this.drcdb=drcdb;
        this.com=com;
        this.band_rate=band_rate;
        this.parity=parity;
        this.stop=stop;
        this.channel_id=channel_id;
        this.name=name;
        this.function_code=function_code;
        this.slave_id=slave_id;
        this.address=address;
        this.count=count;
        this.dataitem_type=dataitem_type;
        this.run_cycle=run_cycle;
        this.IntervalTime=IntervalTime;
    }

    public static List<Byte> execute2Bytes(
        SerialPort sp,int function_code,int slaveID,int address,int quantity_of_x,String com,int band_rate,int parity,int stop,int IntervalTime) throws Exception
    {
        List<Byte> result=new ArrayList<Byte>();
        sp.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);
        String response="";
        byte[] recive_buff=new byte[quantity_of_x*2+5];
        try {
            if(!sp.isOpen()){
                sp.openPort();
            }
            //获取Socket的输出流，用来向Slave端发送数据
            DataOutputStream out = new DataOutputStream (sp.getOutputStream());
            //获取Socket的输入流，用来接收从Slave端发送过来的数据
            DataInputStream in = new DataInputStream(sp.getInputStream());
            int length=6;    //01-04请求帧 功能码+数据长度均为6，1字节功能码
            result.add((byte)(slaveID%256));            //单元标识符
            result.add((byte)(function_code));          //功能码 
            result.add((byte)(address/256));            //地址 H
            result.add((byte)(address%256));            //地址 L
            result.add((byte)(quantity_of_x/256));      //数量 H
            result.add((byte)(quantity_of_x%256));      //数量 L
            int crc=DRModbus_RTU_Master.crc16_modbus(dr_util.ListToBytes(result), 0, length);
            result.add((byte)(crc%256));
            result.add((byte)(crc/256));
            // 向 Slave 端输出请求
            byte[] msg=dr_util.ListToBytes(result);
            try {
                out.write(msg);
                //请求报文日志
                write_log(1,com,String.valueOf(band_rate),String.valueOf(parity),String.valueOf(stop),msg,msg.length);
                Thread.sleep(IntervalTime);
                int data_length=quantity_of_x*2+5;
                in.read(recive_buff,0,data_length);
                // 显示接收、发送内容
                response=dr_util.bytes2hexstr(recive_buff,data_length);
                //回复报文日志
                int receiveLength = dr_util.byteToInt(recive_buff[2])+5;
                byte[] trueReceive = new byte[receiveLength];
                System.arraycopy(recive_buff,0,trueReceive,0,receiveLength);
                write_log(0,com,String.valueOf(band_rate),String.valueOf(parity),String.valueOf(stop),trueReceive,receiveLength);
                System.out.println(String.format("Slave send message:[%s]",response));
                out.close();
                sp.closePort();                
            } catch (Exception e) {
                System.out.println("串口连接失败！");
                throw new Exception();
                // e.printStackTrace();
            }
            return dr_util.BytesToList(recive_buff);
        } catch (Exception e) {
            // e.printStackTrace();
            throw new Exception();
            
        }
        // return dr_util.BytesToList(recive_buff);
    }

    // 针对写入指令（遥控/遥调）的执行指令转字节
    public static List<Byte> execute2Bytes4W(
            SerialPort sp,int function_code,int slaveID,int address,int[] data,String com,String band_rate,String parity,String stop,int IntervalTime) throws Exception
    {
        List<Byte> result=new ArrayList<Byte>();
        sp.setComPortTimeouts(SerialPort.TIMEOUT_WRITE_BLOCKING,0,1000);
        String response="";
        byte[] recive_buff=new byte[512];
        try {
            if(!sp.isOpen()){
                sp.openPort();
            }
            //获取Socket的输出流，用来向Slave端发送数据
            DataOutputStream out = new DataOutputStream (sp.getOutputStream());
            //获取Socket的输入流，用来接收从Slave端发送过来的数据
            DataInputStream in = new DataInputStream(sp.getInputStream());
            int length=6;
            if(function_code==5){
                length=6;    //05请求帧 功能码+数据长度均为6，1字节功能码
                result.add((byte)(slaveID%256));            //单元标识符
                result.add((byte)(function_code));          //功能码
                result.add((byte)(address/256));            //地址 H
                result.add((byte)(address%256));            //地址 L
                if((data[0]&0x01)==0){
                    result.add((byte)(0x00));               //OFF H
                    result.add((byte)(0x00));               //OFF L
                }else{
                    result.add((byte)(0xFF));               //ON H
                    result.add((byte)(0x00));               //ON L
                }
            }else if(function_code==0x0F){
                length=7+(int)Math.ceil(data.length/8.0f);    //0F请求帧 功能码+数据长度=7+数据量/8
                result.add((byte)(slaveID%256));            //单元标识符
                result.add((byte)(function_code));          //功能码
                result.add((byte)(address/256));            //地址 H
                result.add((byte)(address%256));            //地址 L
                result.add((byte)(data.length/256));      //数量 H
                result.add((byte)(data.length%256));      //数量 L
                result.add((byte)(Math.ceil(data.length/8.0f)));            //字节长度
                // 将data数组转换为字节数组
                int[] data_byte=new int[1+data.length/8];
                for(int i=0;i<(int)Math.ceil(data.length/8.0f);i++){
                    data_byte[i]=0;
                    for(int j=0;j<8&&(i*8+j)<data.length;j++){
                        if(data[i*8+j]!=0){
                            data_byte[i]=data_byte[i]|(0x01<<j);
                        }
                    }
                }
                for(int i=0;i<(int)Math.ceil(data.length/8.0f);i++){
                    result.add((byte)(data_byte[i]));
                }
            }else if(function_code==6){
                length=6;    //06请求帧 功能码+数据长度均为6，1字节功能码
                result.add((byte)(slaveID%256));            //单元标识符
                result.add((byte)(function_code));          //功能码
                result.add((byte)(address/256));            //地址 H
                result.add((byte)(address%256));            //地址 L
                result.add((byte)(data[0]/256));            //数值 H
                result.add((byte)(data[0]%256));            //数值 L
            }else if(function_code==16){
                length=7+data.length*2;         //10请求帧 功能码+数据长度=7+数据量*2
                result.add((byte)(slaveID%256));            //单元标识符
                result.add((byte)(function_code));          //功能码
                result.add((byte)(address/256));            //地址 H
                result.add((byte)(address%256));            //地址 L
                result.add((byte)(data.length/256));      //数量 H
                result.add((byte)(data.length%256));      //数量 L
                result.add((byte)(data.length*2));            //字节长度
                for(int i=0;i<data.length;i++){
                    result.add((byte)(data[i]/256));            //数值 H
                    result.add((byte)(data[i]%256));            //数值 L
                }
            }
            int crc=DRModbus_RTU_Master.crc16_modbus(dr_util.ListToBytes(result), 0, length);
            result.add((byte)(crc%256));
            result.add((byte)(crc/256));
            // 向 Slave 端输出请求
            byte[] msg=dr_util.ListToBytes(result);
            try {
                out.write(msg);
                //请求报文日志
                write_log(1,com,band_rate,parity,stop,msg,msg.length);
                Thread.sleep(IntervalTime);
                int data_length;
                data_length=in.read(recive_buff);
                // 显示接收、发送内容
                response=dr_util.bytes2hexstr(recive_buff,data_length);
                //回复报文日志
                int receiveLength = 8;
                byte[] trueReceive = new byte[receiveLength];
                System.arraycopy(recive_buff,0,trueReceive,0,receiveLength);
                write_log(0,com,band_rate,parity,stop,trueReceive,receiveLength);
                System.out.println(String.format("Slave send message:[%s]",response));
                System.out.println(String.format("data_length:[%s]",data_length));
                out.close();
                sp.closePort();
            } catch (Exception e) {
                System.out.println("串口连接失败！");
                throw new Exception();
                // e.printStackTrace();
            }
            return dr_util.BytesToList(recive_buff);
        } catch (Exception e) {
            // e.printStackTrace();
            throw new Exception();

        }
        // return dr_util.BytesToList(recive_buff);
    }

    public static List<byte[]> read_slave_data2byte2(String serial_name,int band_rate,int parity,int stop,
        int function_code,int slaveID,int address,int quantity_of_x,int IntervalTime)
    throws Exception{
        List<byte[]> result=new ArrayList<byte[]>();
        byte[] data;
        int group_index;
        List<Byte> slave_data;
        SerialPort com=null;
        try {
//            SerialPort com=SerialPort.getCommPort(serial_name);
//            com.setComPortParameters(band_rate, 8, stop, parity);
//            List<Byte> slave_data=DRModbus_RTU_Master.execute2Bytes(
//                com,
//                function_code, slaveID, address, quantity_of_x
//                );
//            for(int i=0;i<quantity_of_x;i++){
//                data=new byte[2];
//                data[0]=slave_data.get(3+i*2);
//                data[1]=slave_data.get(4+i*2);
//                result.add(data);
//            }
            if(function_code==1||function_code==2){
                for(group_index=0;group_index*max_group_size*16<quantity_of_x;group_index++){
                    if((quantity_of_x-(group_index*max_group_size*16))<max_group_size*16){
                        com = SerialPort.getCommPort(serial_name);
                        com.setComPortParameters(band_rate, 8, stop, parity);
                        slave_data = DRModbus_RTU_Master.execute2Bytes(
                                com,
                                function_code, slaveID, address + group_index * max_group_size, (quantity_of_x - (group_index * max_group_size)
                                ),serial_name,band_rate,parity,stop,IntervalTime);
                        for(int i=0;i<(quantity_of_x-(group_index*max_group_size*16));i++){
                            if((3+i/8)>slave_data.size())break;
                            data=new byte[1];
                            data[0]=slave_data.get(3+i/8);
                            data[0]=(byte) ((data[0]>>(i%8))&0x01);
                            result.add(data);
                        }
                    }else{
                        com = SerialPort.getCommPort(serial_name);
                        com.setComPortParameters(band_rate, 8, stop, parity);
                        slave_data = DRModbus_RTU_Master.execute2Bytes(
                                com,
                                function_code, slaveID, address + group_index * max_group_size, (quantity_of_x - (group_index * max_group_size)
                                ),serial_name,band_rate,parity,stop,IntervalTime);
                        for(int i=0;i<max_group_size*16;i++){
                            if((3+i/8)>slave_data.size())break;
                            data=new byte[1];
                            data[0]=slave_data.get(3+i/8);
                            data[0]=(byte) (data[0]>>(i%8));
                            result.add(data);
                        }
                    }
                }
            }else if(function_code==3||function_code==4) {
                for (group_index = 0; group_index * max_group_size < quantity_of_x; group_index++) {
                    if ((quantity_of_x - (group_index * max_group_size)) < max_group_size) {
                        com = SerialPort.getCommPort(serial_name);
                        com.setComPortParameters(band_rate, 8, stop, parity);
                        slave_data = DRModbus_RTU_Master.execute2Bytes(
                                com,
                                function_code, slaveID, address + group_index * max_group_size, (quantity_of_x - (group_index * max_group_size)
                                ),serial_name,band_rate,parity,stop,IntervalTime);
                        for (int i = 0; i < (quantity_of_x - (group_index * max_group_size)); i++) {
                            data = new byte[2];
                            data[0] = slave_data.get(3 + i * 2);
                            data[1] = slave_data.get(4 + i * 2);
                            result.add(data);
                        }
                    } else {
                        com = SerialPort.getCommPort(serial_name);
                        com.setComPortParameters(band_rate, 8, stop, parity);
                        slave_data = DRModbus_RTU_Master.execute2Bytes(
                                com,
                                function_code, slaveID, address + group_index * max_group_size, max_group_size
                                ,serial_name,band_rate,parity,stop,IntervalTime);
                        for (int i = 0; i < max_group_size; i++) {
                            data = new byte[2];
                            data[0] = slave_data.get(3 + i * 2);
                            data[1] = slave_data.get(4 + i * 2);
                            result.add(data);
                        }
                    }
                }
            }

        } catch (Exception e) {
            throw new Exception();
        }finally{
            if(com!=null)
                com.closePort();
        }
        return result;
    }

    public static String execute(SerialPort sp,int function_code,int slaveID,int address,int quantity_of_x){
        List<Byte> result=new ArrayList<Byte>();
        String response="";
        try {
//            result=DRModbus_RTU_Master.execute2Bytes(sp,function_code, slaveID, address, quantity_of_x);
            // 显示接收、发送内容
            response=dr_util.bytes2hexstr(dr_util.ListToBytes(result));
            System.out.println(String.format("Slave send message:[%s]",response));
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // return dr_util.ListToBytes(result);
        return response;
    }

    /******************************************************************************
	 * Name:    CRC-16/MODBUS       x16+x15+x2+1
	 * Poly:    0x8005
	 * Init:    0xFFFF
	 * Refin:   True
	 * Refout:  True
	 * Xorout:  0x0000
	 * Note:
	 *****************************************************************************/
    public static int crc16_modbus(byte[] data,int offset,int length){
		int crc = 0xffff;        // Initial value
		length += offset;
		for(int j=offset;j<length;j++) {
			crc = (crc ^ (data[j] & 0xff)) & 0xffff;  // crc ^= *data; data++;
			for(int i = 0; i < 8; i++){
				if ((crc & 1) == 0)
					crc = crc >> 1;
				else
					crc = ((crc >> 1) ^ 0xA001) & 0xffff;          // 0xA001 = reverse 0x8005
			}
		}
		return crc ;
	}

    /**
     * 关联WEB API列表
     * @param api_lists
     * @param drcdb
     */
    public static void associate_actions(List<DRHTTP_API> api_lists,DRCDB drcdb) throws ClassNotFoundException{
        @SuppressWarnings("unchecked")
        Class<?> CLS=(Class<DRModbus_RTU_Master>) Class.forName("DRC.DRModbus.DRModbus_RTU_Master");
        for(Method method:CLS.getDeclaredMethods()){
            FJW_URI fjw_uri=method.getAnnotation(FJW_URI.class);
            System.out.println(method.toString());
            if(fjw_uri!=null){
                System.out.println(method.toString());
                System.out.println(fjw_uri.value());
                try {
                    api_lists.add((DRHTTP_API)method.invoke(CLS,drcdb, fjw_uri.value()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @FJW_URI(value ="modbus/read_serial_ports")
    public static DRHTTP_API read_serial_ports(DRCDB drcdb,String URI){
        return new DRHTTP_API(drcdb,URI){
            @Override
            public String getResult(Map<String, Object> parameters,DR_SESSION drs){
                String content="";
                List<String> sps_name=new ArrayList<String>();
                SerialPort[] sps=SerialPort.getCommPorts();
                // String info="";
                String osName = System.getProperty("os.name").toLowerCase();
                for(SerialPort sp:sps){
                    if(osName.contains("windows")){
                        sps_name.add(sp.getSystemPortName());
                    }else{
                        sps_name.add(sp.getSystemPortPath());
                    }
                }
                dr_ajax_answer daa=new dr_ajax_answer(0, "");
                daa.set_data(sps_name);
                // daa.etc=info;
                content=daa.json_string();
                return content;
            }
        };
    }

    public static String read_modbus_data(String serial_name,int band_rate,int parity,int stop,String function_code,String slave_id,
        String address,String count){
        String result="";
        String content="";
        try {
            SerialPort com=SerialPort.getCommPort(serial_name);
            // com.setComPortParameters(9600, 8, SerialPort.ONE_STOP_BIT, SerialPort.EVEN_PARITY);
            com.setComPortParameters(band_rate, 8, stop, parity);
            result=DRModbus_RTU_Master.execute(com,Integer.parseInt(function_code),
                Integer.parseInt(slave_id),Integer.parseInt(address), Integer.parseInt(count));
            content=dr_ajax_answer.sample_json_string(0,result);
        } catch (Exception e) {
            content=dr_ajax_answer.sample_json_string(1,"读取失败");
        }
        return content;
    }

    @Override
    public void run(){
        DRCDB drcdb=this.drcdb;
        String sqlstr;
        record_data_set di_rds;
        float value;
        int data_type;
        int register_type;
        byte[] data;
        // 暂时仅处理输入寄存器和保持寄存器
        // 2022年12月19日 罗继东
        if(this.function_code==4)
            register_type=3;
        else if(this.function_code==3)
            register_type=4;
        else register_type=4;
        channel4collect ch4c=null;
        dataItem4collect di4c=null;
        for(int i=0;i<channels4collect.size();i++){
            if(channels4collect.get(i).channel_id==this.channel_id){
                ch4c=channels4collect.get(i);
                break;
            }
        }
        while(this.runMark&&ch4c!=null){
            try {
                List<byte[]> slave_data=DRModbus_RTU_Master.read_slave_data2byte2(
                    this.com,this.band_rate,this.parity,this.stop,
                    this.function_code,this.slave_id,this.address,this.count,this.IntervalTime
                );
                System.out.println("this.address:"+this.address);
                sqlstr="select dataItem_id,label,address,data_type,coefficient,negation,BCD,ABS,base_value from dataItem4collect";
                sqlstr+=" where channel_id="+this.channel_id;
                di_rds=drcdb.executeQuerySQL(sqlstr);
                System.out.println(di_rds.datas.size());
                System.out.println(slave_data.size());
                for(int di_index=0;di_index<ch4c.ds4c.size()&&di_index<slave_data.size();di_index++){
                    di4c=ch4c.ds4c.get(di_index);
                    data_type=di4c.data_type;
                    if(di_index==(ch4c.ds4c.size()-1)&&data_type>2&&data_type<7)break;
                    value=0;
                    switch (data_type){
                        case 1:
                            value=dr_util.byte2toshort_s(slave_data.get(
                                    di4c.address-address
                            ));
                            break;
                        case 2:
                            value=dr_util.byte2toshort_b(slave_data.get(
                                    di4c.address-address
                            ));
                            break;
                        case 3:
                            data=new byte[4];
                            data[0]=slave_data.get(
                                    di4c.address-address
                            )[0];
                            data[1]=slave_data.get(
                                    di4c.address-address
                            )[1];
                            data[2]=slave_data.get(
                                    di4c.address-address+1
                            )[0];
                            data[3]=slave_data.get(
                                    di4c.address-address+1
                            )[1];
                            value=dr_util.byte4tofloat_s(data);
                            break;
                        case 4:
                            data=new byte[4];
                            data[0]=slave_data.get(
                                    di4c.address-address
                            )[0];
                            data[1]=slave_data.get(
                                    di4c.address-address
                            )[1];
                            data[2]=slave_data.get(
                                    di4c.address-address+1
                            )[0];
                            data[3]=slave_data.get(
                                    di4c.address-address+1
                            )[1];
                            value=dr_util.byte4tofloat_s2(data);
                            break;
                        case 5:
                            data=new byte[4];
                            data[0]=slave_data.get(
                                    di4c.address-address
                            )[0];
                            data[1]=slave_data.get(
                                    di4c.address-address
                            )[1];
                            data[2]=slave_data.get(
                                    di4c.address-address+1
                            )[0];
                            data[3]=slave_data.get(
                                    di4c.address-address+1
                            )[1];
                            value=dr_util.byte4tofloat_b(data);
                            break;
                        case 6:
                            data=new byte[4];
                            data[0]=slave_data.get(
                                    di4c.address-address
                            )[0];
                            data[1]=slave_data.get(
                                    di4c.address-address
                            )[1];
                            data[2]=slave_data.get(
                                    di4c.address-address+1
                            )[0];
                            data[3]=slave_data.get(
                                    di4c.address-address+1
                            )[1];
                            value=dr_util.byte4tofloat_b2(data);
                            break;
                        case 7:
                            value=slave_data.get(
                                    di4c.address-address
                            )[0];
                            break;
                        default:
                            value=0;
                    }
                    // 根据系数转换值
                    value=value*Float.parseFloat(di_rds.datas.get(di_index).get("coefficient"));
                    // 根据取反设定转换值
                    if(Integer.parseInt(di_rds.datas.get(di_index).get("negation"))==1)
                        value=-1*value;
                    // 根据绝对值设定转换值
                    if(Integer.parseInt(di_rds.datas.get(di_index).get("ABS"))==1)
                        value=Math.abs(value);
                    // 根据基值转换值
                    value=value+Float.parseFloat(di_rds.datas.get(di_index).get("base_value"));
//                    if(dataItem4collect.updateLocalDataItem(drcdb, channel_id,
//                            slave_id,register_type,
//                            Integer.parseInt(di_rds.datas.get(di_index).get("address")),
//                            value))
//                        System.out.println(name+":"
//                                +di_rds.datas.get(di_index).get("label")
//                                +":写入完成！["+value+"]");
                    Date now=new Date();
                    SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
                    System.out.println("当前时间:"+ft.format(now));
                    if(this.dataitem_type==0){
                        di4c.value=value;
                        di4c.timestamp=new Date();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // System.out.println(e);
                System.out.println(name+":["+this.com+"]连接失败！");
            }
            try {
                for(int loop_index=0;loop_index<this.run_cycle;loop_index++){
                    Thread.sleep(1000);
                    if(!this.runMark)break;
                }
            } catch (InterruptedException e) {
                // e.printStackTrace();
                System.out.println(String.format("采集通道[%s]停止！",name));
            }
        }
    }

    /**
     * 写入日志函数
     * @param direction 0:接收 1发送
     * @param indestCOM  目标串口
     * @param indestBand_rate 目标波特率
     * @param indestParity 目标奇偶校验
     * @param indestStop 目标停止位
     * @param data       帧内容
     * @param data_length   帧内容长度
     * @throws IOException
     */
    public static void write_log(int direction,String indestCOM,String indestBand_rate,String indestParity,String indestStop,byte[] data,int data_length) throws IOException {
        int logSwitch = Integer.parseInt(DRCDB.read_conf_with_name("log_switch", "conf.ini"));
        if(logSwitch==1) {
            //根据帧内容生成最终的buff，并写入日志文件
            String destIP = indestCOM + "-" + indestBand_rate + "-" + indestParity + "-" + indestStop;
            String log;
            if (direction == 0)
                log = destIP + ":RX<<" + dr_util.bytes2hexstr(data, data_length);
            else
                log = destIP + ":TX>>" + dr_util.bytes2hexstr(data, data_length);
            writeLog(log);
        }
    }

    /**
     * 写日志函数
     * @param inStr
     * @throws IOException
     */
    public static void writeLog(String inStr) throws IOException {
        //写入日志函数
        //按日期和日志前缀拼接出日志文件名，向文件尾写入输入的字符串内容
        Date dNow = new Date( );
        SimpleDateFormat ft = new SimpleDateFormat ("yyyyMMdd");

        String logFileName=logPrefix+ft.format(dNow)+".log";

        // 转换为Path对象
        Path logPath = Paths.get(logFileName);
        // 提取目录路径
        Path dirPath = logPath.getParent();
        // 检查目录是否存在，如果不存在则创建
        if (!Files.exists(dirPath)) {
            try {
                Files.createDirectories(dirPath);
                System.out.println("Modbus 目录已创建");
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }

        File logFile = new File(logFileName);
        if(!logFile.exists()){
            logFile.createNewFile();
        }
        FileWriter fileWriter=new FileWriter(logFile,true);
        SimpleDateFormat ft2 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
        fileWriter.write("["+ft2.format(dNow)+"]"+inStr+"\n");
        fileWriter.close();
    }

    public static void main(String[] args){
        // DRModbus_RTU_Master dcm=new DRModbus_RTU_Master("127.0.0.1", 502);
        // DRModbus_RTU_Master drm=new DRModbus_RTU_Master();
        // SerialPort com2=SerialPort.getCommPort("COM2");
        // com2.setComPortParameters(9600, 8, SerialPort.ONE_STOP_BIT, SerialPort.EVEN_PARITY);
        // String result=DRModbus_RTU_Master.execute(com2,3, 1, 4, 2);
        // System.out.println(result);
        // System.out.println(DRModbus_RTU_Master.read_modbus_data("com2", "3", "1", "0","10"));
        // System.out.println(DRModbus_RTU_Master.read_serial_ports());
        // List<byte[]> d;
        // try {
        //     d = DRModbus_RTU_Master.read_slave_data2byte2(
        //         "COM2",9600,2,1, 3, 1, 0, 10);
        //     for(int i=0;i<d.size();i++){
        //         System.out.println(dr_util.bytes2hexstr(d.get(i)));
        //         System.out.println(dr_util.byte2toshort_b(d.get(i)));
        //     }
        // } catch (Exception e) {
        //     e.printStackTrace();
        // }
        SerialPort[] commPorts = SerialPort.getCommPorts();
        for (SerialPort port : commPorts) {
            System.out.println("Found serial port: " + port.getSystemPortName());
            System.out.println("Port description: " + port.getDescriptivePortName());
            System.out.println("Port open?: " + port.isOpen());
        }
    }
}
